/**
* j-Interop (Pure Java implementation of DCOM protocol)
*     
* Copyright (c) 2013 Vikram Roopchand
* 
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Vikram Roopchand  - Moving to EPL from LGPL v3.
*  
*/

package org.jinterop.dcom.core;


import java.net.UnknownHostException;

import org.jinterop.dcom.common.JIDefaultAuthInfoImpl;
import org.jinterop.dcom.common.JIErrorCodes;
import org.jinterop.dcom.common.JIException;
import org.jinterop.dcom.common.JISystem;
import org.jinterop.winreg.IJIWinReg;
import org.jinterop.winreg.JIPolicyHandle;
import org.jinterop.winreg.JIWinRegFactory;


/**<p>Wrapper class used to define user friendly <code>ProgID</code>.
 * <p> Definition from MSDN: <i>
 *  A ProgID, or programmatic identifier, is a registry entry that can be associated
 *  with a CLSID. The format of a ProgID is <Vendor>.<Component>.<Version>, separated
 *  by periods and with no spaces, as in Word.Document.6. Like the CLSID, the ProgID
 *  identifies a class, but with less precision.
 *  </i>
 * <p>
 * This class uses the <code>WINREG</code> service to get the mapping between the <code>ProgId</code>
 * and the <code>CLSID</code>.
 * <p>
 * The <code>WINREG</code> package of j-Interop is capable of querying the Windows registry in a
 * platform independent way using SMB. The internal database is looked up first before
 * making calls to <code>WINREG</code> service.
 * </p>
 * @since 1.0
 */
public class JIProgId  {

	private String progId = null;
	private JIClsid clsid = null;
	private JISession session = null;
	private String server = null;
	private boolean autoRegister = false;

	/** Indicates to the framework, if Windows Registry settings for DLL\OCX
	 * component identified by this object should be modified to add a <code>Surrogate</code>
	 * automatically. A <code>Surrogate</code> is a process which provides resources
	 * such as memory and cpu for a DLL\OCX to execute.
	 *
	 * @param autoRegister <code>true</code> if auto registration should be done by the framework.
	 */
	public void setAutoRegistration(boolean autoRegister)
	{
		this.autoRegister = autoRegister;
	}

	/**Returns the status of the auto registration flag for the component identified by this object.
	 *
	 * @return <code>true</code> if the auto registration flag is set.
	 */
	public boolean isAutoRegistrationSet()
	{
		return autoRegister;
	}

	private JIProgId(String progId)
	{
		this.progId = progId;
		clsid = JIClsid.valueOf(JISystem.getClsidFromProgId(progId));
	}

	void setServer(String server)
	{
		this.server = server;
	}

	private void getIdFromWinReg() throws JIException
	{
		IJIWinReg winreg;
		//winreg = JIWinRegFactory.getSingleTon().getWinreg(new JIDefaultAuthInfoImpl(session.getDomain(),session.getUserName(),session.getPassword()),server,true);
		//System.out.println("Encoding the password...");

//		try {
//			winreg = JIWinRegFactory.getSingleTon().getWinreg(new JIDefaultAuthInfoImpl(session.getDomain(),session.getUserName(),URLEncoder.encode(session.getPassword(),"UTF-8")),server,true);
//		} catch (UnsupportedEncodingException e) {
//			try {
//				winreg = JIWinRegFactory.getSingleTon().getWinreg(new JIDefaultAuthInfoImpl(session.getDomain(),session.getUserName(),URLEncoder.encode(session.getPassword(),System.getProperty("file.encoding"))),server,true);
//			} catch (UnsupportedEncodingException e1) {
//				throw new JIException(JIErrorCodes.JI_WINREG_EXCEPTION2);
//			}catch (UnknownHostException e2)
//			{
//				throw new JIException(JIErrorCodes.JI_WINREG_EXCEPTION3);
//			}
//		} catch (UnknownHostException e)
//		{
//			throw new JIException(JIErrorCodes.JI_WINREG_EXCEPTION3);
//		}

		if (server == null)
		{
			server = session.getTargetServer();
		}

		try {
			if (session.isSSOEnabled())
			{
				winreg = JIWinRegFactory.getSingleTon().getWinreg(server,true);	
			}
			else
			{
				winreg = JIWinRegFactory.getSingleTon().getWinreg(new JIDefaultAuthInfoImpl(session.getDomain(),session.getUserName(),session.getPassword()),server,true);
			}
			
		} catch (UnknownHostException e)
		{
			throw new JIException(JIErrorCodes.JI_WINREG_EXCEPTION3);
		}
		JIPolicyHandle handle = winreg.winreg_OpenHKLM();
		JIPolicyHandle handle2 = winreg.winreg_OpenKey(handle,"SOFTWARE\\Classes\\" + progId + "\\CLSID",IJIWinReg.KEY_READ);
		String key = new String(winreg.winreg_QueryValue(handle2,255));
		winreg.winreg_CloseKey(handle2);
		winreg.winreg_CloseKey(handle);
		winreg.closeConnection();
		//seperate the {}
		clsid = JIClsid.valueOf(key.substring(key.indexOf("{") + 1,key.indexOf("}")));
		clsid.setAutoRegistration(autoRegister);
		JISystem.internal_setClsidtoProgId(progId,clsid.getCLSID());

	}

	/** Factory method returning an instance of this class.
	 *
	 * @param progId user-friendly string representation such as "Excel.Application"
	 * @return
	 */
	public static JIProgId valueOf(String progId)
	{
		return new JIProgId(progId);
	}

	/** Returns the <code>CLSID</code> for this <code>ProgId</code>.
	 *
	 * @return
	 * @throws JIException
	 */
	public JIClsid getCorrespondingCLSID() throws JIException
	{
		if (clsid == null)
		{
			getIdFromWinReg();
		}
		return clsid;
	}

	void setSession(JISession session)
	{
		this.session = session;
	}
}
